package com.hrh.hrhaiagent.app;


import com.hrh.hrhaiagent.advisor.MyLoggerAdvisor;
import com.hrh.hrhaiagent.chatmemory.FileBasedChatMemory;
import com.hrh.hrhaiagent.rag.TripAppRagCloudAdvisorConfig;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;


import java.util.List;
import java.util.concurrent.Flow;

import static cn.hutool.core.lang.Console.log;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY;

@Component
@Slf4j
public class TripApp {
    private final ChatClient chatClient;

    private static final String SYSTEMP_PROMPT = "扮演旅游规划的专家。开场向用户表明身份，告知用户可协助规划旅游。" +
            "围绕计划中、已预订、旅途中三种状态提问：计划中状态询问目的地偏好、预算时间及出行需求；" +
            "已预订状态询问行程细节优化、潜在问题及备选方案；旅途中状态询问突发状况、体验调整及即时建议。" +
            "引导用户详述具体需求、已有安排及当前挑战，以便给出专属解决方案。";

    public TripApp(ChatModel dashscopeChatModel){
        String fileDir = System.getProperty("user.dir") + "/chat-memory";
        // 初始化基于内存的对话记忆
//        ChatMemory chatMemory = new InMemoryChatMemory();
        ChatMemory chatMemory = new FileBasedChatMemory(fileDir);
        chatClient = ChatClient.builder(dashscopeChatModel)
                .defaultSystem(SYSTEMP_PROMPT)
                .defaultAdvisors(
                        new MessageChatMemoryAdvisor(chatMemory),
                        new MyLoggerAdvisor()
                )
                .build();
    }

    /**
     * AI 基础对话
     * @param message
     * @param chatId
     * @return
     */
    public String doChat(String message, String chatId) {
        // 构建聊天响应对象，通过聊天客户端发起请求
        ChatResponse response = chatClient
                .prompt() // 准备聊天提示
                .user(message) // 设置用户输入的消息
                // 配置聊天顾问参数，包括聊天记忆的会话ID和检索的历史对话数量
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .call() // 发起聊天请求
                .chatResponse(); // 获取聊天响应
        // 从响应中提取聊天结果的文本内容
        String content = response.getResult().getOutput().getText();
        //  打印聊天内容
        System.out.println(content);
        // 返回聊天内容
        return content;
    }

    record TripReport(String title, List<String> suggestions) {
    }


    /**
     * AI 格式化输出
     * @param message
     * @param chatId
     * @return
     */
    public TripReport doChatWithReport(String message, String chatId) {
        TripReport tripReport = chatClient
                .prompt()
                .system(SYSTEMP_PROMPT + "每次对话后都要生成计划结果，标题为{用户名}的旅行计划报告，内容为建议列表")
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .call()
                .entity(TripReport.class);
        log.info("tripReporport: {}", tripReport);
        return tripReport;
    }

    @Resource
    private VectorStore tripAppVectorStore;

    @Resource
    private Advisor TripAppRagCloudAdvisor;

    /**
     * RAG 对话
     * @param message
     * @param chatId
     * @return
     */
    public String doChatWithRag(String message, String chatId){
        ChatResponse response = chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .advisors(new MyLoggerAdvisor())
//                .advisors(new QuestionAnswerAdvisor(tripAppVectorStore))
                // 应用 RAG 检索增强服务
                .advisors(TripAppRagCloudAdvisor)
                .call()
                .chatResponse();
        String content = response.getResult().getOutput().getText();
        log.info("content: {}", content);
        return content;
    }

    /**
     * 流式对话
     * @param message
     * @param chatId
     * @return
     */
    public Flux<String> doChatByStream(String message, String chatId) {
        return chatClient
                .prompt()
                .user(message)
                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
                .stream()
                .content();
    }

//    @Resource
//    private ToolCallbackProvider toolCallbackProvider;
//
//    /**
//     * MCP 对话
//     * @param message
//     * @param chatId
//     * @return
//     */
//    public String doChatWithMcp(String message, String chatId){
//        ChatResponse response = chatClient
//                .prompt()
//                .user(message)
//                .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
//                        .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
//                .advisors(new MyLoggerAdvisor())
//                .tools(toolCallbackProvider)
//                .call()
//                .chatResponse();
//        String content = response.getResult().getOutput().getText();
//        log.info("content: {}", content);
//        return content;
//    }

}
